/*
 * Description:agent管理类
 */
#include "agent_manager.h"
#include <windows.h>
#include <fstream>
#include <tchar.h>
#include "common.h"
#include <thread>
#include "log.h"
#include "error.h"
#include "rpc_service/sendto_host.h"
#include "shellapi.h"
#include "app_filter/app_filter_manager.h"
#include "common/session_utils.h"
#include "common/guest_utils.h"
#include "common/win_update_utils.h"
#include "dfx/app_using_statistics.h"
#include "share_folder/share_folder_helper.h"
#include "performance/perf_pipe_reciever.h"
#include "performance/perf_process_preload.h"
#include "performance/oop_context_menu_host.h"
#include "performance/install_lifecycle_handler.h"
#include "process_load_statistic/payload_sensor.h"
#include "power_consumption/application_monitor.h"
#include "power_consumption/power_manager.h"
#include "dfx/stability/event_reporter.h"
#include "dfx/diskpart_report.h"
#include "rpc_service/guest_manager.h"
#include "dfx/driver_report.h"
#ifdef _FUZZ
#include "GuestLinkFuzzWindowsClient.h"
#endif

using namespace std;
using namespace COMMON;

namespace GUEST {

const int WAIT_TIME = 1000;
const wchar_t* PRODUCTS[] = {
    L"C:\\Windows\\System32\\drivers\\viostor.sys",
    L"C:\\Windows\\System32\\drivers\\netkvm.sys",
    L"C:\\Windows\\System32\\drivers\\pvpanic.sys",
    L"C:\\Windows\\System32\\drivers\\viofs.sys",
    L"C:\\Windows\\System32\\drivers\\viogpudo.sys",
    L"C:\\Windows\\System32\\drivers\\vioinput.sys",
    L"C:\\Windows\\System32\\drivers\\vioser.sys",
    L"C:\\Windows\\System32\\drivers\\svgampwddm.sys",
    L"C:\\Windows\\System32\\drivers\\ivshmem.sys",
    L"C:\\Windows\\System32\\drivers\\balloon.sys",
    L"C:\\Windows\\System32\\drivers\\hwfs.sys",
    L"C:\\Windows\\System32\\drivers\\scream.sys",
    L"C:\\ProgramData\\VMAgent\\driver1\\viogpu\\vmgtsrv.exe",
    L"C:\\ProgramData\\VMAgent\\driver1\\viogpu\\vmgtsharemgr.exe",
    L"C:\\ProgramData\\VMAgent\\agent_service.exe",
    nullptr
};

int AgentManager::Init()
{
    LOG_INFO("AgentManager Init");
    GuestUtils::ExecCmd("pnputil.exe /scan-devices /async", false, false);
    m_sendtoHost->BootComplete();
    WinUpdateUtils::RestoreSetting();
    PERF_PIPE_RECIEVER.Init(m_sendtoHost);
    SHARE_FOLDER_HELPER.Init(m_sendtoHost);
    APPLICATION_MONITOR.Init();
    PAYLOAD_SENSOR.Init(m_sendtoHost);
    POWER_MANAGER.Init(m_sendtoHost);
    INSTALL_LIFECYCLE_HANDLER.Init();
    APP_USING_STATISTICS.Init();
    OOP_CONTEXT_HOST.Init();
    APP_USING_REPORT.Init(m_sendtoHost);
    EVENT_REPORTER.Init(m_sendtoHost);
    DISKPART_REPORT.Init(m_sendtoHost);
    APP_FILTER_MANAGER.Init();
    DRIVER_REPORT.Init(m_sendtoHost);
    GUEST_MANAGER.LogProductName(PRODUCTS);
    PROCESSDETECT.Init(m_sendtoHost);
    GUEST_MANAGER.LogDriverInfo();
#ifdef _FUZZ
    TEST::GuestLinkFuzzWindowsClient::StartFuzz(m_sendtoHost);
#endif
    return OK;
}

int AgentManager::GustLinkInit()
{
    try {
        m_sendtoHost = make_shared<WINCONTROL::SendToHost>("GuestAgent");
        GUEST_MANAGER.SetSendToHost(m_sendtoHost);
    } catch (const std::bad_alloc& e) {
        LOG_ERR("m_sendtoHost init failed.");
        return DEFAULT_ERROR;
    }
    int sendRet = m_sendtoHost->ConnectServer();
    if (sendRet != OK) {
        LOG_ERR("Connect SendToHost event failed.");
    }

    LOG_DEBUG("Start init RecvFromHost");
    m_recvfromHost = make_unique<RecvFromHost>();
    int recvRet = m_recvfromHost->InitService();
    if (recvRet != OK) {
        LOG_ERR("RecvFromHost init failed.");
    }
    return sendRet == OK && recvRet == OK;
}

void AgentManager::Quit()
{
    PAYLOAD_SENSOR.Quit();
    APPLICATION_MONITOR.Quit();
    POWER_MANAGER.Quit();
    OOP_CONTEXT_HOST.Quit();
    APP_USING_STATISTICS.Quit();
    INSTALL_LIFECYCLE_HANDLER.Quit();
    APP_USING_REPORT.Deinit();
    DRIVER_REPORT.Deinit();
    if (m_recvfromHost->GetForceShutdownState()) {
        std::map<std::string, std::string> eventData = {
            {CALL_TYPE, "0"}
        };
        EVENT_REPORTER.ReportEventData(SA_VM_QUICK_SHUTDOWN, eventData);
        m_recvfromHost->QuickShutdown();
        m_recvfromHost->SetForceShutdownState(false);
    }
    EVENT_REPORTER.Deinit();
    int ret = m_recvfromHost->DeInitService();
    if (ret != OK) {
        LOG_ERR("RecvFromHost Deinit failed {}", ret);
    }
    ret = m_sendtoHost->DisConnectServer();
    if (ret != OK) {
        LOG_ERR("disConnect SendToHost event failed {}", ret);
    }
    ret = SHARE_FOLDER_HELPER.Deinit();
    if (ret != OK) {
        LOG_ERR("share folder deinit failed {}", ret);
    }
    PERF_PROCESS_PRELOAD.CloseAllPreloadProcess();
    APP_FILTER_MANAGER.Deinit();
    PROCESSDETECT.Deinit();
    m_stopVMAgent = true;
    LOG_INFO("Quit VMAgent");
}

void AgentManager::Shutdown()
{
    LOG_INFO("Notify guest shutdown");
    m_sendtoHost->Shutdown();
}

void AgentManager::QuickStartShutdown()
{
    LOG_INFO("Notify guest quickStart shutdown");
    m_sendtoHost->QuickStartShutdown();
}
}  // namespace GUEST